package net.fpeg.kotlin.msa.gateway

import com.auth0.jwt.JWT
import com.auth0.jwt.algorithms.Algorithm
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.cloud.gateway.filter.GlobalFilter
import org.springframework.core.Ordered
import org.springframework.core.io.buffer.DataBuffer
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.nio.charset.StandardCharsets
import java.util.*

@Component
class MyGlobalFilter : GlobalFilter, Ordered {
    fun returnError(exchange: ServerWebExchange): Mono<Void> {
        exchange.response.statusCode = HttpStatus.UNAUTHORIZED
        exchange.response.headers.add("Content-Type", "application/json;charset=UTF-8")
        val bytes: ByteArray = "{\"value\":\"授权错误\"}".toByteArray(StandardCharsets.UTF_8)
        val buffer: DataBuffer = exchange.response.bufferFactory().wrap(bytes)
        return exchange.response.writeWith(Flux.just(buffer))
    }

    fun String.decodeJwtId() = try {
        JWT
                .require(Algorithm.HMAC256("SECRET"))
                .build()
                .verify(this.substring(7))
                .getClaim("id")
                .asInt()
    } catch (ex: Exception) {
        null
    }


    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        if (exchange != null && chain != null) {
            val url = exchange.request.uri.path
            val authorizations = exchange.request.headers["Authorization"]
            return when {
                url.startsWith("/auth/login") || url.startsWith("/auth/register") -> chain.filter(exchange)
                authorizations == null -> returnError(exchange)
                authorizations[0].decodeJwtId() == null -> returnError(exchange)
                else -> {
                    return chain.filter(exchange.mutate().request(
                            exchange.request
                                    .mutate()
                                    .header("USER_ID", authorizations[0].decodeJwtId().toString())
                                    .build()
                    ).build())
                }
            }
        }
        return chain.filter(exchange)
    }

    override fun getOrder() = 0
}